use crate::ast::*;
use crate::error::{CompilerError, Result};
use inkwell::types::BasicTypeEnum;
use inkwell::values::BasicValueEnum;
use inkwell::AddressSpace;

use super::super::LLVMBackend;

impl<'ctx> LLVMBackend<'ctx> {
    /// Execute all deferred statements in LIFO order
    pub(super) fn generate_new_expression(
        &mut self,
        new_expr: &NewExpr,
    ) -> Result<BasicValueEnum<'ctx>> {
        // 1. 确定数据类型
        let data_type = match new_expr.type_name.as_str() {
            "int" | "i32" => self.context.i32_type().into(),
            "i8" => self.context.i8_type().into(),
            "i16" => self.context.i16_type().into(),
            "i64" => self.context.i64_type().into(),
            "f32" => self.context.f32_type().into(),
            "f64" => self.context.f64_type().into(),
            "bool" => self.context.bool_type().into(),
            _ => {
                // 对于复杂类型，暂时使用i32作为占位符
                // TODO: 实现完整的类型系统查找
                self.context.i32_type().into()
            }
        };

        // 2. 创建引用计数对象结构：{ref_count: i32, data: T}
        let struct_type = match data_type {
            BasicTypeEnum::IntType(int_type) => self
                .context
                .struct_type(&[self.context.i32_type().into(), int_type.into()], false),
            BasicTypeEnum::FloatType(float_type) => self
                .context
                .struct_type(&[self.context.i32_type().into(), float_type.into()], false),
            _ => {
                // 默认结构：{ref_count: i32, data: i32}
                self.context.struct_type(
                    &[
                        self.context.i32_type().into(),
                        self.context.i32_type().into(),
                    ],
                    false,
                )
            }
        };

        // 3. 分配内存
        let malloc_func = self.module.get_function("malloc").unwrap_or_else(|| {
            let malloc_type = self
                .context
                .i8_type()
                .ptr_type(AddressSpace::default())
                .fn_type(&[self.context.i64_type().into()], false);
            self.module.add_function("malloc", malloc_type, None)
        });

        let size = struct_type.size_of().unwrap();
        let ptr = self
            .builder
            .build_call(malloc_func, &[size.into()], "malloc_call")?;
        let ptr_value = ptr.try_as_basic_value().left().unwrap();

        // 将i8*指针转换为结构体指针
        let struct_ptr = match ptr_value {
            BasicValueEnum::PointerValue(ptr_val) => self.builder.build_bitcast(
                ptr_val,
                struct_type.ptr_type(AddressSpace::default()),
                "struct_ptr",
            )?,
            _ => {
                return Err(CompilerError::internal(
                    "Expected pointer value from malloc",
                ))
            }
        };

        // 将BasicValueEnum转换为PointerValue
        let struct_ptr_value = match struct_ptr {
            BasicValueEnum::PointerValue(ptr) => ptr,
            _ => {
                return Err(CompilerError::internal(
                    "Expected pointer value from bitcast",
                ))
            }
        };

        // 4. 初始化引用计数为1

        // 初始化引用计数字段
        let ref_count_ptr = unsafe {
            self.builder.build_gep(
                struct_type,
                struct_ptr_value,
                &[
                    self.context.i32_type().const_int(0, false),
                    self.context.i32_type().const_int(0, false),
                ],
                "ref_count_ptr",
            )?
        };

        let initial_ref_count = self.context.i32_type().const_int(1, false);
        self.builder.build_store(ref_count_ptr, initial_ref_count)?;

        // 5. 如果有初始化器，执行初始化
        if let Some(ref initializer) = new_expr.initializer {
            let data_ptr = unsafe {
                self.builder.build_gep(
                    struct_type,
                    struct_ptr_value,
                    &[
                        self.context.i32_type().const_int(0, false),
                        self.context.i32_type().const_int(1, false),
                    ],
                    "data_ptr",
                )?
            };

            let init_value = self.generate_expression(initializer)?;
            self.builder.build_store(data_ptr, init_value)?;
        } else {
            // 如果没有初始化器，将数据字段初始化为0
            let data_ptr = unsafe {
                self.builder.build_gep(
                    struct_type,
                    struct_ptr_value,
                    &[
                        self.context.i32_type().const_int(0, false),
                        self.context.i32_type().const_int(1, false),
                    ],
                    "data_ptr",
                )?
            };

            let zero_value: BasicValueEnum<'ctx> = match data_type {
                BasicTypeEnum::IntType(int_type) => int_type.const_int(0, false).into(),
                BasicTypeEnum::FloatType(float_type) => float_type.const_float(0.0).into(),
                _ => self.context.i32_type().const_int(0, false).into(),
            };
            self.builder.build_store(data_ptr, zero_value)?;
        }

        Ok(struct_ptr_value.into())
    }

    /// Generate struct expression (struct literal)
    pub(super) fn generate_struct_expression(
        &mut self,
        struct_expr: &StructExpr,
    ) -> Result<BasicValueEnum<'ctx>> {
        // Check if this is actually a basic type (shouldn't happen directly, but handle it)
        if struct_expr.fields.len() == 1 && struct_expr.fields[0].name == "__value__" {
            // This is a basic type value wrapped in struct syntax
            // Just return the unwrapped value
            return self.generate_expression(&struct_expr.fields[0].value);
        }

        // Extract struct name from struct_type
        let struct_name = match &struct_expr.struct_type {
            Type::Struct(struct_type) => &struct_type.name,
            Type::Generic(name) => name,
            _ => {
                return Err(CompilerError::internal(&format!(
                    "Invalid struct type in struct expression: {:?}",
                    struct_expr.struct_type
                )))
            }
        };

        // Look up the struct type definition
        if let Some(struct_decl) = self.struct_declarations.get(struct_name) {
            // Clone the struct declaration to avoid borrowing issues
            let struct_decl = struct_decl.clone();

            // Generate LLVM types for each field
            let mut field_types = Vec::new();
            for field in &struct_decl.fields {
                let field_llvm_type =
                    self.nrc_type_to_llvm_type(&Some(field.field_type.clone()))?;
                field_types.push(field_llvm_type.into());
            }

            let struct_type = self.context.struct_type(&field_types, false);

            // Allocate memory for the struct
            let alloca = self.builder.build_alloca(struct_type, "struct_alloca")?;

            // Initialize fields with provided values or defaults
            for field_init in &struct_expr.fields {
                // Find the field index in the struct declaration
                let field_index = struct_decl
                    .fields
                    .iter()
                    .position(|field| field.name == field_init.name)
                    .ok_or_else(|| {
                        CompilerError::internal(&format!("Unknown field: {}", field_init.name))
                    })?;

                // Generate the field value
                let field_value = self.generate_expression(&field_init.value)?;

                // Get field pointer
                let field_ptr = unsafe {
                    self.builder.build_gep(
                        struct_type,
                        alloca,
                        &[
                            self.context.i32_type().const_int(0, false), // struct pointer
                            self.context.i32_type().const_int(field_index as u64, false), // field index
                        ],
                        &format!("field_{}_ptr", field_init.name),
                    )?
                };

                // Store the field value
                let _ = self.builder.build_store(field_ptr, field_value);
            }

            // Check if this struct has an init method and call it
            if struct_decl.get_method("init").is_some() {
                // Call the init method with the struct instance
                self.call_init_method(&struct_decl, alloca)?;
            }

            // Load the struct value from the alloca (after potential init modifications)
            let struct_value = self
                .builder
                .build_load(struct_type, alloca, "struct_value")?;
            Ok(struct_value)
        } else {
            Err(CompilerError::internal(&format!(
                "Struct declaration not found: {}",
                struct_name
            )))
        }
    }

    /// Generate tuple expression (tuple literal)
    pub(super) fn generate_tuple_expression(
        &mut self,
        tuple_expr: &TupleExpr,
    ) -> Result<BasicValueEnum<'ctx>> {
        // Generate element values and collect their types
        let mut element_values = Vec::new();
        let mut element_types: Vec<inkwell::types::BasicTypeEnum> = Vec::new();

        for element in &tuple_expr.elements {
            let element_value = self.generate_expression(element)?;
            element_types.push(element_value.get_type());
            element_values.push(element_value);
        }

        // Create LLVM struct type for the tuple
        let tuple_type = self.context.struct_type(&element_types, false);

        // Allocate memory for the tuple
        let alloca = self.builder.build_alloca(tuple_type, "tuple_alloca")?;

        // Store each element value
        for (index, element_value) in element_values.iter().enumerate() {
            let field_ptr = unsafe {
                self.builder.build_gep(
                    tuple_type,
                    alloca,
                    &[
                        self.context.i32_type().const_int(0, false), // struct pointer
                        self.context.i32_type().const_int(index as u64, false), // element index
                    ],
                    &format!("tuple_elem_{}_ptr", index),
                )?
            };

            let _ = self.builder.build_store(field_ptr, *element_value);
        }

        // Load and return the complete tuple value
        let tuple_value = self.builder.build_load(tuple_type, alloca, "tuple_value")?;
        Ok(tuple_value)
    }
}
